package org.chaosmo;

import org.openjdk.jmh.annotations.Benchmark;
import org.openjdk.jmh.annotations.BenchmarkMode;
import org.openjdk.jmh.annotations.Fork;
import org.openjdk.jmh.annotations.Measurement;
import org.openjdk.jmh.annotations.Mode;
import org.openjdk.jmh.annotations.OutputTimeUnit;
import org.openjdk.jmh.annotations.Scope;
import org.openjdk.jmh.annotations.Setup;
import org.openjdk.jmh.annotations.State;
import org.openjdk.jmh.annotations.Threads;
import org.openjdk.jmh.annotations.Warmup;
import org.openjdk.jmh.results.format.ResultFormatType;
import org.openjdk.jmh.runner.Runner;
import org.openjdk.jmh.runner.RunnerException;
import org.openjdk.jmh.runner.options.Options;
import org.openjdk.jmh.runner.options.OptionsBuilder;

import java.sql.Array;
import java.util.ArrayList;
import java.util.Date;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

@BenchmarkMode(Mode.AverageTime)
@Warmup(iterations = 5)
@Measurement(iterations = 5, time = 5, timeUnit = TimeUnit.SECONDS)
@Threads(5)
@Fork(1)
@OutputTimeUnit(TimeUnit.MILLISECONDS)
@State(Scope.Thread)
public class RemoveByIteratorBenchmark {


    private List<Integer> arrList1 = null;
    private List<Integer> linList1 = null;
    private List<Integer> arrList2 = null;
    private List<Integer> linList2 = null;
    private List<Integer> arrList3 = null;
    private List<Integer> linList3 = null;

    @Setup
    public void prepareData() {
        arrList1 = new ArrayList<>();
        for (int i = 0; i < 100000; i++) {
            arrList1.add(i);
        }

        linList1 = new LinkedList<>();
        for (int i = 0; i < 100000; i++) {
            linList1.add(i);
        }

        arrList2 = new ArrayList<>();
        for (int i = 0; i < 100000; i++) {
            arrList2.add(i);
        }

        linList2 = new LinkedList<>();
        for (int i = 0; i < 100000; i++) {
            linList2.add(i);
        }

        arrList3 = new ArrayList<>();
        for (int i = 0; i < 100000; i++) {
            arrList3.add(i);
        }

        linList3 = new LinkedList<>();
        for (int i = 0; i < 100000; i++) {
            linList3.add(i);
        }
    }

    public static void main(String[] args) throws RunnerException {
        Options options = new OptionsBuilder()
                .include(RemoveByIteratorBenchmark.class.getSimpleName())
//                .output("/Users/chaosmo/workspace/jmhresult")
                .resultFormat(ResultFormatType.JSON)
                .build();
        new Runner(options).run();

    }

    @Benchmark
    public void removeEvensByStreamFilterArrayList() {//利用streamfilter
        arrList3 = arrList3.stream().filter(i->i%2 != 0).collect(Collectors.toList());
    }

    @Benchmark
    public void removeEvensByStreamFilterLinkedList() {//利用streamfilter
        linList3 = linList3.stream().filter(i->i%2 != 0).collect(Collectors.toList());
    }

    @Benchmark
    public void removeEvensByIteratorArrayList() {//利用迭代器remove偶数
        Iterator<Integer> itr = arrList2.iterator();
        while (itr.hasNext()) {

            if (itr.next() % 2 == 0)
                itr.remove();
        }
    }
    @Benchmark
    public void removeEvensByIteratorLinkedList() {//利用迭代器remove偶数
        Iterator<Integer> itr = linList2.iterator();
        while (itr.hasNext()) {

            if (itr.next() % 2 == 0)
                itr.remove();
        }
    }

    @Benchmark
    public void removeEvensArrayList() {//不使用迭代器remove偶数
        int i = 0;
        while (i < arrList1.size()) {

            if (arrList1.get(i) % 2 == 0) {
                arrList1.remove(i);
            } else {
                i++;
            }
        }
    }

    @Benchmark
    public void removeEvensLinkedList() {//不使用迭代器remove偶数
        int i = 0;
        while (i < linList1.size()) {

            if (linList1.get(i) % 2 == 0) {
                linList1.remove(i);
            } else {
                i++;
            }
        }
    }
}
